package org.ytor.core.sysapi.codegen.logic;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.ytor.common.exception.BaseException;
import org.ytor.common.exception.DownloadException;
import org.ytor.common.util.Strs;
import org.ytor.core.holder.U;
import org.ytor.core.model.LoginUser;
import org.ytor.core.sysapi.codegen.config.CodeGeneratorConfig;
import org.ytor.core.sysapi.codegen.model.ColumnMeta;
import org.ytor.core.sysapi.codegen.model.TableMeta;
import org.ytor.core.sysapi.codegen.service.IMetaService;
import org.ytor.core.sysapi.codegen.service.ITemplateFillService;
import org.ytor.core.sysapi.codegen.service.support.TemplateFillServiceImpl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * created by yangtong on 2025/4/6 下午4:57
 * <br/>
 * 代码生成服务
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class CodeGenLogic {
    private final CodeGeneratorConfig config;
    private final IMetaService metaService;

    public byte[] gen(@NonNull String basePath, @NonNull String module, String schema, String tableName) {
        if (config == null) {
            throw new BaseException("代码生成器配置信息初始化未成功");
        }
        basePath = basePath.trim();
        module = module.trim();

        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ZipOutputStream zipOut = new ZipOutputStream(baos)) {
            List<TableMeta> tableMetas = metaService.listTables(null, schema, tableName);
            if (tableMetas.isEmpty()) {
                throw new DownloadException("未找到表【" + tableName + "】");
            }
            TableMeta tableMeta = tableMetas.getFirst();
            List<ColumnMeta> columnMetas = metaService.listColumns(null, schema, tableMeta.getTable());
            List<String> keys = metaService.listPrimaryKeys(null, schema, tableMeta.getTable());
            //过滤表的字段
            List<ColumnMeta> columns = new ArrayList<>();
            for (ColumnMeta columnMeta : columnMetas) {
                //将下划线转为小驼峰
                String columnName = Strs.toLowerCamelCase(columnMeta.getColumnName());
                columnMeta.setColumnName(columnName);
                //判断是否主键
                columnMeta.setIsPrimaryKey(keys.contains(columnMeta.getColumnName()));
                //判断对应Java类型
                String javaType = config.getJavaType("MYSQL", columnMeta.getColumnType().toLowerCase());
                String tsType = config.getTsType(javaType);
                columnMeta.setJavaType(javaType);
                columnMeta.setTsType(tsType);
                //过滤掉十大基本字段
                if (!Strs.contain(columnName, "id", "createTime", "createBy", "updateTime", "updateBy", "departCode", "remark", "delFlag", "version", "status")) {
                    columns.add(columnMeta);
                }
            }

            LoginUser loginUser = U.get();
            String currentUser;
            if (loginUser != null) {
                currentUser = loginUser.getRealName();
            } else {
                currentUser = "yangtong";
            }

            //生成该表的模型数据
            String comment = tableMeta.getComment();
            if (Strs.isEmpty(comment)) {
                comment = tableMeta.getTable();
            }
            Map<String, Object> model = new HashMap<>();
            model.put("path", basePath);
            model.put("module", module);
            model.put("currentUser", currentUser);
            model.put("table_name", tableMeta.getTable());
            model.put("tableName", Strs.toLowerCamelCase(tableMeta.getTable()));
            model.put("TableName", Strs.toUpperCamelCase(tableMeta.getTable()));
            model.put("TableComment", comment);
            model.put("columnMetas", columns);

            //生成模板数据
            ITemplateFillService templateFillService = new TemplateFillServiceImpl(model);
            // 写入模板渲染结果到 ZIP
            String codePath = "src/" + basePath.replace(".", "/") + "/" + module + "/";
            for (String templatePath : templateFillService.listTemplateNames()) {
                String renderedName = templateFillService.renderFileName(templatePath);
                if (renderedName.endsWith(".ftl")) {
                    renderedName = renderedName.substring(0, renderedName.length() - 4);
                }
                String renderedContent = templateFillService.renderContent(templatePath);

                zipOut.putNextEntry(new ZipEntry(codePath + renderedName));
                zipOut.write(renderedContent.getBytes(StandardCharsets.UTF_8));
                zipOut.closeEntry();
            }

            zipOut.finish();
            return baos.toByteArray();
        } catch (IOException | SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
